package com.zhaoqi.hr.service;

import com.zhaoqi.hr.dto.request.LoginRequest;
import com.zhaoqi.hr.dto.request.RegisterRequest;
import com.zhaoqi.hr.dto.request.WechatPhoneLoginRequest;
import com.zhaoqi.hr.dto.response.JwtResponse;
import com.zhaoqi.hr.util.WechatUtil;
import com.zhaoqi.hr.entity.User;
import com.zhaoqi.hr.repository.UserRepository;
import com.zhaoqi.hr.util.JwtUtil;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 认证服务
 */
@Service
public class AuthService {

    private static final Logger log = LoggerFactory.getLogger(AuthService.class);

    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private SmsService smsService;

    /**
     * 用户注册
     */
    @Transactional
    public User register(RegisterRequest request) {
        // 检查手机号是否已存在
        if (userRepository.existsByPhone(request.getPhone())) {
            throw new RuntimeException("手机号已被注册");
        }

        // 验证短信验证码
        if (!smsService.verifyCode(request.getPhone(), request.getSmsCode())) {
            throw new RuntimeException("短信验证码错误");
        }

        // 创建用户
        User user = new User();
        user.setPhone(request.getPhone());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setRole(request.getRole());
        user.setRealName(request.getRealName());
        user.setStatus(User.UserStatus.PENDING);

        User savedUser = userRepository.save(user);
        log.info("用户注册成功: {}", savedUser.getPhone());
        
        return savedUser;
    }

    /**
     * 用户登录（支持用户名或手机号）
     */
    public JwtResponse login(LoginRequest request) {
        // 查找用户（支持用户名或手机号）
        User user = findUserByUsernameOrPhone(request.getUsername());

        // 检查用户状态
        if (user.getStatus() == User.UserStatus.SUSPENDED) {
            throw new RuntimeException("账户已被暂停");
        }

        // 使用用户名进行认证（统一使用username作为认证标识）
        String authIdentifier = user.getUsername();
        
        // 创建认证令牌进行密码验证
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(authIdentifier, request.getPassword())
        );

        SecurityContextHolder.getContext().setAuthentication(authentication);

        // 生成JWT令牌
        String jwt = jwtUtil.generateToken(authentication);

        log.info("用户登录成功: {} ({})", user.getUsername(), user.getPhone());
        
        return new JwtResponse(jwt, user.getId(), user.getUsername(), user.getPhone(), user.getRole().name());
    }

    /**
     * 根据用户名或手机号查找用户
     */
    private User findUserByUsernameOrPhone(String identifier) {
        // 先尝试用户名查找
        Optional<User> userOpt = userRepository.findByUsername(identifier);
        if (userOpt.isPresent()) {
            return userOpt.get();
        }
        
        // 再尝试手机号查找
        userOpt = userRepository.findByPhone(identifier);
        if (userOpt.isPresent()) {
            return userOpt.get();
        }
        
        throw new RuntimeException("用户名或密码错误");
    }

    /**
     * 发送短信验证码
     */
    public void sendSmsCode(String phone) {
        smsService.sendVerificationCode(phone);
        log.info("短信验证码已发送: {}", phone);
    }

    /**
     * 微信手机号授权登录
     */
    @Transactional
    public JwtResponse wechatPhoneLogin(WechatPhoneLoginRequest request) {
        try {
            log.info("=== 微信授权登录开始 ===");
            log.info("请求参数 - code: {}, role: {}", request.getCode(), request.getRole());
            
            // 1. 获取微信session信息
            WechatUtil.WechatSessionInfo sessionInfo = wechatUtil.getWechatSession(request.getCode());
            log.info("获取微信session - openid: {}, sessionKey: {}", sessionInfo.getOpenid(), sessionInfo.getSessionKey());
            
            // 2. 解密手机号
            String phoneNumber = wechatUtil.decryptWechatPhone(request.getEncryptedData(), request.getIv(), sessionInfo.getSessionKey());
            log.info("解密手机号: {}", phoneNumber);
            
            // 3. 查找或创建用户
            User user = findOrCreateWechatUser(phoneNumber, request.getRole(), sessionInfo.getOpenid());
            log.info("用户信息 - ID: {}, 用户名: {}, 手机号: {}, openid: {}", 
                    user.getId(), user.getUsername(), user.getPhone(), user.getWechatOpenid());
            
            // 4. 生成JWT令牌
            String jwt = jwtUtil.generateTokenForUser(user);
            
            log.info("微信授权登录成功: {} ({})", user.getUsername(), user.getPhone());
            log.info("=== 微信授权登录结束 ===");
            
            return new JwtResponse(jwt, user.getId(), user.getUsername(), user.getPhone(), user.getRole().name());
            
        } catch (Exception e) {
            log.error("微信授权登录失败", e);
            throw new RuntimeException("微信授权登录失败: " + e.getMessage());
        }
    }

    /**
     * 当前手机号登录
     */
    @Transactional
    public JwtResponse currentPhoneLogin(WechatPhoneLoginRequest request) {
        try {
            // 1. 通过微信code获取session_key和openid
            WechatUtil.WechatSessionInfo sessionInfo = wechatUtil.getWechatSession(request.getCode());
            
            // 2. 解密手机号数据
            String phoneNumber = wechatUtil.decryptWechatPhone(request.getEncryptedData(), 
                                                   request.getIv(), 
                                                   sessionInfo.getSessionKey());
            
            // 3. 查找已有用户
            Optional<User> userOpt = userRepository.findByPhone(phoneNumber);
            if (!userOpt.isPresent()) {
                throw new RuntimeException("该手机号尚未注册，请先注册");
            }
            
            User user = userOpt.get();
            
            // 4. 检查用户状态
            if (user.getStatus() == User.UserStatus.SUSPENDED) {
                throw new RuntimeException("账户已被暂停");
            }
            
            // 5. 更新微信openid（如果没有的话）
            if (user.getWechatOpenid() == null || user.getWechatOpenid().isEmpty()) {
                user.setWechatOpenid(sessionInfo.getOpenid());
                userRepository.save(user);
            }
            
            // 6. 生成JWT令牌
            String jwt = jwtUtil.generateTokenForUser(user);
            
            log.info("当前手机号登录成功: {} ({})", user.getUsername(), user.getPhone());
            
            return new JwtResponse(jwt, user.getId(), user.getUsername(), user.getPhone(), user.getRole().name());
            
        } catch (Exception e) {
            log.error("当前手机号登录失败", e);
            throw new RuntimeException("当前手机号登录失败: " + e.getMessage());
        }
    }

    @Autowired
    private WechatUtil wechatUtil;


    /**
     * 查找或创建微信用户
     */
    private User findOrCreateWechatUser(String phoneNumber, String role, String openid) {
        log.info("=== 查找或创建微信用户 ===");
        log.info("输入参数 - 手机号: {}, 角色: {}, openid: {}", phoneNumber, role, openid);
        
        // 先查找是否已有该手机号的用户
        Optional<User> userOpt = userRepository.findByPhone(phoneNumber);
        log.info("根据手机号查找用户结果: {}", userOpt.isPresent() ? "找到用户" : "未找到用户");
        
        if (userOpt.isPresent()) {
            // 用户已存在，更新微信openid
            User user = userOpt.get();
            log.info("用户已存在 - ID: {}, 用户名: {}, openid: {}", user.getId(), user.getUsername(), user.getWechatOpenid());
            
            if (user.getWechatOpenid() == null || user.getWechatOpenid().isEmpty()) {
                user.setWechatOpenid(openid);
                userRepository.save(user);
                log.info("更新用户openid: {}", openid);
            }
            return user;
        } else {
            // 创建新用户
            log.info("创建新用户开始...");
            User user = new User();
            user.setPhone(phoneNumber);
            
            // 基于手机号生成唯一用户名，添加后缀避免重复
            String[] surnames = {"张", "李", "王", "刘", "陈", "杨", "赵", "黄", "周", "吴"};
            String[] names = {"伟", "芳", "娜", "敏", "静", "丽", "强", "磊", "军", "洋"};
            
            int surnameIndex = Math.abs(phoneNumber.hashCode()) % surnames.length;
            int nameIndex = Math.abs((phoneNumber + "name").hashCode()) % names.length;
            String baseName = surnames[surnameIndex] + names[nameIndex];
            
            // 检查用户名是否已存在，如果存在则添加手机号后4位作为后缀
            String realName = baseName;
            if (userRepository.findByUsername(baseName).isPresent()) {
                String phoneSuffix = phoneNumber.substring(phoneNumber.length() - 4);
                realName = baseName + phoneSuffix;
                log.info("用户名{}已存在，添加后缀生成: {}", baseName, realName);
            }
            
            log.info("生成用户名逻辑 - 手机号: {}, phoneNumber.hashCode(): {}, surnameIndex: {}, nameIndex: {}, 最终用户名: {}", 
                    phoneNumber, phoneNumber.hashCode(), surnameIndex, nameIndex, realName);
            
            user.setUsername(realName);
            user.setPassword(passwordEncoder.encode("wechat_" + System.currentTimeMillis()));
            user.setRole(User.UserRole.valueOf(role));
            user.setWechatOpenid(openid);
            user.setStatus(User.UserStatus.APPROVED);
            user.setRealName(realName);
            
            User savedUser = userRepository.save(user);
            log.info("新用户创建成功 - ID: {}, 用户名: {}, 手机号: {}", savedUser.getId(), savedUser.getUsername(), savedUser.getPhone());
            log.info("=== 创建微信用户结束 ===");
            
            return savedUser;
        }
    }

    /**
     * 获取当前登录用户
     */
    public User getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new RuntimeException("用户未登录");
        }
        String username = authentication.getName();
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
    }
}
